package com.freejy.ecommunity.utils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.freejy.ecommunity.common.Global;
import org.apache.commons.lang3.StringUtils;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;


/**
 * @author Jerry
 * @date 2013-10-06
 */
public class JedisManager {

	private final Logger log = LoggerFactory.getLogger(JedisManager.class);

	private static List<JedisPool> readPool = new ArrayList<JedisPool>();
	private static List<JedisPool> writePool = new ArrayList<JedisPool>();

    private static String keyPerfix;

    private static int refreshPeriod;
    
    private static int DEFAULT_INDEX = 0;
	
	private static JedisManager instance = new JedisManager();
	
	static{
		if (StringUtils.isBlank(keyPerfix))
		{
			keyPerfix = "";
		}
		initPool();
	}
	
	private JedisManager() {
    }
	
	public static JedisManager getInstance() {
		return instance;
	}
	
	/**
	 * 初始化jedis配置
	 */
	private static void initPool(){
		try {
			JedisPoolConfig config = new JedisPoolConfig();
			config.setMaxTotal(Integer.parseInt(Global.getConfig("redis.maxActive", "50")));
			config.setMaxIdle(Integer.parseInt(Global.getConfig("redis.maxIdle", "5")));
			config.setMinIdle(Integer.parseInt(Global.getConfig("redis.maxWait", "5000")));
			config.setTestOnBorrow(Boolean.parseBoolean(Global.getConfig("redis.testOnBorrow", "false")));
			config.setTestOnReturn(Boolean.parseBoolean(Global.getConfig("redis.testOnReturn", "false")));
			
			String refPeriod = Global.getConfig("redis.expire");
			JedisManager.refreshPeriod = StringUtils.isNotBlank(refPeriod) ? Integer.parseInt(refPeriod) : -1;
			String _host = Global.getConfig("redis.host", "127.0.0.1");
			int _port = Integer.parseInt(Global.getConfig("redis.port", "6379"));
			//TODO 单台或集群设置
			JedisPool pool = new JedisPool(config, _host, _port, 100000);
			writePool.add(pool);
			readPool.add(pool);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	private JedisPool getEnableCacheWriter()
	{
		JedisPool pool = null;
		for (JedisPool jp : writePool)
		{
			Jedis jedis = null;
			try
			{
				jedis = jp.getResource();
//				jedis.ping();
				pool=jp;
				break;
			}catch (Exception e) {
				log.error("#Exception : not get pool Object for enable write", e);
				e.printStackTrace();
			} finally {
				if (jedis != null)
				{
//					jp.returnResource(jedis);
					jedis.close();
				}
			}
		}
		if (pool == null)
		{
			log.error("#Error : not get pool Object for enable write");
		}
		return pool;
	}
	
	private JedisPool getEnableCacheReader()
	{
		JedisPool pool=null;
		for (JedisPool jp : readPool)
		{
			Jedis jedis=null;
			try
			{
				jedis=jp.getResource();
				//jedis.ping();
				pool=jp;
				break;
			}catch (Exception e) {
				log.error("#Exception : not get pool Object for enable write", e);
				e.printStackTrace();
			} finally {
				if (jedis != null)
				{
//					jp.returnResource(jedis);
					jedis.close();
				}
			}
		}
		if (pool==null)
		{
			log.error("#Error : not get pool Object for enable write");
		}
		return pool;
	}
	
	protected String ObjectToJSON(Object obj)
	{
		if (obj==null)
		{
			throw new NullPointerException("null对象无法序列化为json");
		}
		ByteArrayOutputStream out=new ByteArrayOutputStream();
		try {
		    ObjectMapper jsonmap=new ObjectMapper();
			jsonmap.writeValue(out, obj);
			return out.toString("utf-8");
		} catch (JsonGenerationException e) {
			throw new RuntimeException(e);
		} catch (JsonMappingException e) {
			throw new RuntimeException(e);
		} catch (IOException e) {
			throw new RuntimeException(e);
		}finally
		{
			try {
				out.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
//		return null;
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	protected Object JSONToObject(String json,Class type)
	{
		ByteArrayInputStream bis = null;
		try {
			if (json==null||json.length()<1) {
				return null;
			}
			bis = new ByteArrayInputStream(json.getBytes("utf-8"));
			InputStreamReader input=new InputStreamReader(bis, "utf-8");
			ObjectMapper jsonmap=new ObjectMapper();
			return jsonmap.readValue(input, type);
		} catch (UnsupportedEncodingException e) {
			log.error("#Error : JSON To Object error"+json);
			throw new RuntimeException(e);
		} catch (JsonParseException e) {
			log.error("#Error : JSON To Object error"+json);
			throw new RuntimeException(e);
		} catch (JsonMappingException e) {
			log.error("#Error : JSON To Object error"+json);
			throw new RuntimeException(e);
		} catch (IOException e) {
			log.error("#Error : JSON To Object error"+json);
			throw new RuntimeException(e);
		}finally
		{
			try {
				if (bis!=null)bis.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	public String get(Integer index, String key) 
	{
		JedisPool pool = null;
		Jedis jedis = null;
		try {
			pool= getEnableCacheReader();
			jedis = pool.getResource();
			if (index == null)
			{
				index = DEFAULT_INDEX;
			}
			jedis.select(index);
			String res = jedis.get(keyPerfix + key);
			if (res != null && res.equals("nil"))
			{
				log.error("#Error : not get correct Value of redis - " + res);
				return null;
			}
			return res;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		} finally {
			if (pool != null && jedis != null)
			{
//				pool.returnResource(jedis);
				jedis.close();
			}
		}
	}
	
	@SuppressWarnings({ "rawtypes"})
	public Object get(Integer index, String key, Class beanClass) 
	{
		JedisPool pool = null;
		Jedis jedis = null;
		try {
			pool= getEnableCacheReader();
			jedis = pool.getResource();
			if (index == null)
			{
				index = DEFAULT_INDEX;
			}
			jedis.select(index);
			String json = jedis.get(keyPerfix + key);
			if (json != null && json.equals("nil"))
			{
				log.error("#Error : not get correct Value of redis - " + json);
				return null;
			}
			return this.JSONToObject(json, beanClass);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		} finally {
			if (pool != null && jedis != null)
			{
//				pool.returnResource(jedis);
				jedis.close();
			}
		}
	}
	
	/**
	 * 检查指定的key是否存在,若 key 存在，返回 1 ，否则返回 0
	 * @param key
	 * @return
	 */
	public boolean Exists(Integer index, String key) 
	{
		JedisPool pool = null;
		Jedis jedis = null;
		try {
			pool= getEnableCacheReader();
			jedis = pool.getResource();
			if (index == null)
			{
				index = DEFAULT_INDEX;
			}
			jedis.select(index);
			return jedis.exists(keyPerfix + key);
		} catch (Exception e) {
			log.error("#Error : redis调用Exists出错！");
			throw new RuntimeException(e);
		} finally {
			if (pool != null && jedis != null)
			{
//				pool.returnResource(jedis);
				jedis.close();
			}
		}
	}
 

	public void set(Integer index, String key, Object obj) {
		JedisPool pool = null;
		Jedis jedis = null;
		try {
			String json = this.ObjectToJSON(obj);
			pool = getEnableCacheWriter();
			jedis = pool.getResource();
			if (index == null)
			{
				index = DEFAULT_INDEX;
			}
			jedis.select(index);
			jedis.set(keyPerfix + key, json);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}finally {
			if (pool != null && jedis != null)
			{
//				pool.returnResource(jedis);
				jedis.close();
			}
		}
	}
	
	public void set(Integer index, String key, Object obj, long second) 
	{
		JedisPool pool = null;
		Jedis jedis = null;
		try {
			String json = this.ObjectToJSON(obj);
			pool = getEnableCacheWriter();
			jedis = pool.getResource();
			if (index == null)
			{
				index = DEFAULT_INDEX;
			}
			jedis.select(index);
			jedis.setex(keyPerfix + key,(int)second,json);
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			if (pool != null && jedis != null)
			{
//				pool.returnResource(jedis);
				jedis.close();
			}
		}
	}
	
	public void set(Integer index, String key, String value) {
		JedisPool pool = null;
		Jedis jedis = null;
		try {
			pool = getEnableCacheWriter();
			jedis = pool.getResource();
			if (index == null)
			{
				index = DEFAULT_INDEX;
			}
			jedis.select(index);
			jedis.set(keyPerfix + key, (String)value);
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			if (pool != null && jedis != null)
			{
//				pool.returnResource(jedis);
				jedis.close();
			}
		}
	}
	
	public void set(Integer index, String key, String value, long second) {
		JedisPool pool = null;
		Jedis jedis = null;
		try {
			pool = getEnableCacheWriter();
			jedis = pool.getResource();
			if (index == null)
			{
				index = DEFAULT_INDEX;
			}
			jedis.select(index);
			jedis.setex(keyPerfix + key,(int)second ,(String)value);
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			if (pool != null && jedis != null)
			{
//				pool.returnResource(jedis);
				jedis.close();
			}
		}
	}
	
	public void setRS(Integer index, String key, Object obj) {
		JedisPool pool = null;
		Jedis jedis = null;
		try {
			String json = this.ObjectToJSON(obj);
			pool = getEnableCacheWriter();
			jedis = pool.getResource();
			if (index == null)
			{
				index = DEFAULT_INDEX;
			}
			jedis.select(index);
			jedis.setex(keyPerfix + key, refreshPeriod, json);
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			if (pool != null && jedis != null)
			{
//				pool.returnResourceObject(jedis);
				jedis.close();
			}
		}
	}
	
	public void setRS(Integer index, String key, String value) {
		JedisPool pool = null;
		Jedis jedis = null;
		try {
			pool = getEnableCacheWriter();
			jedis = pool.getResource();
			if (index == null)
			{
				index = DEFAULT_INDEX;
			}
			jedis.select(index);
			jedis.setex(keyPerfix + key, refreshPeriod, (String)value);
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			if (pool != null && jedis != null)
			{
//				pool.returnResourceObject(jedis);
				jedis.close();
			}
		}
	}
	
	@SuppressWarnings({ "rawtypes" })
	public Object hget(Integer index, String key,String field,Class cls) {
		JedisPool pool = null;
		Jedis jedis = null;
		try {
			pool = getEnableCacheReader();
			jedis = pool.getResource();
			if (index == null)
			{
				index = DEFAULT_INDEX;
			}
			jedis.select(index);
			String json=jedis.hget(keyPerfix + key,field);
			jedis.close();
			if (json != null && json.equals("nil")) {
				log.error("#Error : not get correct Value of redis - "+json);
				return null;
			}
			return this.JSONToObject(json, cls);
		} catch (Exception e) {
			if (pool != null && jedis != null)
			{
//				pool.returnResourceObject(jedis);
				jedis.close();
			}
			e.printStackTrace();
		}
		return null;
	}
	
	public String hget(Integer index, String key,String field) {
		JedisPool pool = null;
		Jedis jedis = null;
		try {
			pool = getEnableCacheReader();
			jedis = pool.getResource();
			if (index == null)
			{
				index = DEFAULT_INDEX;
			}
			jedis.select(index);
			String json=jedis.hget(keyPerfix + key,field);
			jedis.close();
			if (json != null && json.equals("nil")) {
				log.error("# Error : not get correct Value of redis - "+json);
				return null;
			}
			return json;
		} catch (Exception e) {
			if (pool != null && jedis != null)
			{
//				pool.returnResourceObject(jedis);
				jedis.close();
			}
			e.printStackTrace();
		}
		return null;
	}
	
	public void hdel(Integer index, String key,String field) {
		JedisPool pool = null;
		Jedis jedis = null;
		try {
			pool = getEnableCacheWriter();
			jedis = pool.getResource();
			if (index == null)
			{
				index = DEFAULT_INDEX;
			}
			jedis.select(index);
			jedis.hdel(keyPerfix + key,field);
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			if (pool != null && jedis != null)
			{
//				pool.returnResourceObject(jedis);
				jedis.close();
			}
		}
	}
	
	public List<String> hvals(Integer index, String key) {
		JedisPool pool = null;
		Jedis jedis = null;
		try {
			pool = getEnableCacheReader();
			jedis = pool.getResource();
			if (index == null)
			{
				index = DEFAULT_INDEX;
			}
			jedis.select(index);
			return jedis.hvals(keyPerfix + key);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (pool != null && jedis != null)
			{
//				pool.returnResourceObject(jedis);
				jedis.close();
			}
		}
		return null;
	}
	
	public void hset(Integer index, String key, String field, Object obj) {
		JedisPool pool = null;
		Jedis jedis = null;
		try {
			String json = this.ObjectToJSON(obj);
			pool = getEnableCacheWriter();
			jedis = pool.getResource();
			if (index == null)
			{
				index = DEFAULT_INDEX;
			}
			jedis.select(index);
			jedis.hset(keyPerfix + key,field ,json);
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			if (pool != null && jedis != null)
			{
//				pool.returnResourceObject(jedis);
				jedis.close();
			}
		}
	}
	
	/**
	 * hset
	 * @param index
	 * @param key
	 * @param field
	 * @param json
	 */
	public void hset(Integer index, String key,String field,String json) {
		JedisPool pool = null;
		Jedis jedis = null;
		try {
			pool = getEnableCacheWriter();
			jedis = pool.getResource();
			if (index == null)
			{
				index = DEFAULT_INDEX;
			}
			jedis.select(index);
			jedis.hset(keyPerfix + key,field ,json);
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			if (pool != null && jedis != null)
			{
//				pool.returnResourceObject(jedis);
				jedis.close();
			}
		}
	}
	
	/**
	 * 将key中的数值加num
	 * @param key
	 * @param field
	 * @param num
	 * @return
	 */
	public Long hincrby(Integer index, String key, String field, long num) {
		JedisPool pool = null;
		Jedis jedis = null;
		try {
			pool = getEnableCacheWriter();
			jedis = pool.getResource();
			if (index == null)
			{
				index = DEFAULT_INDEX;
			}
			jedis.select(index);
			return jedis.hincrBy(keyPerfix + key, field ,num);
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			if (pool != null && jedis != null)
			{
//				pool.returnResourceObject(jedis);
				jedis.close();
			}
		}
	}
	
	/**
	 * 同时将多个 field-value (域-值)对设置到哈希表 key 中
	 * @param key
	 * @param map
	 */
	public void hmset(Integer index, String key, Map<String, String> map) 
	{
		JedisPool pool = null;
		Jedis jedis = null;
		try {
			pool = getEnableCacheWriter();
			jedis = pool.getResource();
			if (index == null)
			{
				index = DEFAULT_INDEX;
			}
			jedis.select(index);
			jedis.hmset(keyPerfix + key, map);
		} catch (Exception e) 
		{
			throw new RuntimeException(e);
		} finally {
			if (pool != null && jedis != null)
			{
//				pool.returnResourceObject(jedis);
				jedis.close();
			}
		}
	}
	
	/**
	 * hash length
	 * @param index
	 * @param key
	 * @return
	 */
	public long hlen(Integer index, String key) 
	{
		JedisPool pool = null;
		Jedis jedis = null;
		try
		{
			pool = getEnableCacheReader();
			jedis = pool.getResource();
			if (index == null)
			{
				index = DEFAULT_INDEX;
			}
			jedis.select(index);
			return jedis.hlen(keyPerfix + key);
		} catch (Exception e)
		{
			e.printStackTrace();
			return 0;
		} finally {
			if (pool != null && jedis != null)
			{
//				pool.returnResourceObject(jedis);
				jedis.close();
			}
		}
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public List hgetAll(Integer index, String key, Class cls) 
	{
		JedisPool pool = null;
		Jedis jedis = null;
		try 
		{
			pool = getEnableCacheReader();
			jedis = pool.getResource();
			if (index == null)
			{
				index = DEFAULT_INDEX;
			}
			jedis.select(index);
			Map<String, String> res = jedis.hgetAll(keyPerfix + key);
			jedis.close();
			List list = new ArrayList();
			if (res != null && res.size() > 0)
			{
				res.values().parallelStream().forEach(obj -> list.add(JSONToObject(obj.toString(), cls)));
//				Object[] objs = res.values().toArray();
//				for (Object obj : objs)
//				{
//					list.add(JSONToObject(obj.toString(), cls));
//				}
			}
			return list;
		} catch (Exception e) {
			if (pool != null && jedis != null)
			{
//				pool.returnResourceObject(jedis);
				jedis.close();
			}
			e.printStackTrace();
		}
		return null;
	}
	
	public Map<String, String> hgetAll (Integer index, String key) 
	{
		JedisPool pool = null;
		Jedis jedis = null;
		try {
			pool = getEnableCacheReader();
			jedis = pool.getResource();
			if (index == null)
			{
				index = DEFAULT_INDEX;
			}
			jedis.select(index);
			return jedis.hgetAll(keyPerfix + key);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		} finally {
			if (pool != null && jedis != null)
			{
//				pool.returnResourceObject(jedis);
				jedis.close();
			}
		}
	}
	
	/**
	 * 删除给定的一个或多个 key, 不存在的 key 会被忽略。
	 * @param key
	 * @return 被删除 key 的数量
	 */
	public void Del (Integer index, String key)
	{
		JedisPool pool = null;
		Jedis jedis = null;
		try {
			pool = getEnableCacheWriter();
			jedis = pool.getResource();
			if (index == null)
			{
				index = DEFAULT_INDEX;
			}
			jedis.select(index);
			jedis.del(keyPerfix + key);
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			if (pool != null && jedis != null)
			{
//				pool.returnResourceObject(jedis);
				jedis.close();
			}
		}
	}
	
	public void flushAll () 
	{
		JedisPool pool= getEnableCacheWriter();
		Jedis jedis=pool.getResource();
		jedis.flushAll();
//		pool.returnResourceObject(jedis);
		jedis.close();
	}
	
	/**
	 * 以秒为单位，返回给定 key 的剩余生存时间
	 * 当 key 不存在时，返回 -2; 当 key 存在但没有设置剩余生存时间时，返回 -1; 否则，以秒为单位，返回 key 的剩余生存时间。
	 * @param key
	 * @return 
	 */
	public long Ttl (Integer index, String key) 
	{
		JedisPool pool = null;
		Jedis jedis = null;
		try
		{
			pool= getEnableCacheReader();
			jedis= pool.getResource();
			if (index == null)
			{
				index = DEFAULT_INDEX;
			}
			jedis.select(index);
			return jedis.ttl(keyPerfix + key);
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			if (pool != null && jedis != null)
			{
//				pool.returnResourceObject(jedis);
				jedis.close();
			}
		}
	}
	
	/**
	 * 为给定 key 设置生存时间
	 * @param key
	 * @param second
	 * @return 设置成功返回 1
	 */
	public long expire (Integer index, String key, long second) 
	{
		JedisPool pool = null;
		Jedis jedis = null;
		try
		{
			pool = getEnableCacheWriter();
			jedis = pool.getResource();
			if (index == null)
			{
				index = DEFAULT_INDEX;
			}
			jedis.select(index);
			return jedis.expire(keyPerfix + key,(int)second);
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			if (pool != null && jedis != null)
			{
//				pool.returnResourceObject(jedis);
				jedis.close();
			}
		}
	}
	
	/**
	 * 将key中的数值加一
	 * @param key
	 * @return
	 */
	public long Incr (Integer index, String key) 
	{
		JedisPool pool = null;
		Jedis jedis = null;
		try
		{
			pool = getEnableCacheWriter();
			jedis = pool.getResource();
			if (index == null)
			{
				index = DEFAULT_INDEX;
			}
			jedis.select(index);
			return jedis.incr(keyPerfix + key);
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			if (pool != null && jedis != null)
			{
//				pool.returnResourceObject(jedis);
				jedis.close();
			}
		}
	}
	
	/**
	 * 将key中的数值加num
	 * @param key
	 * @param num
	 * @return
	 */
	public long Incrby (Integer index, String key, int num) 
	{
		JedisPool pool = null;
		Jedis jedis = null;
		try
		{
			pool = getEnableCacheWriter();
			jedis = pool.getResource();
			if (index == null)
			{
				index = DEFAULT_INDEX;
			}
			jedis.select(index);
			return jedis.incrBy(keyPerfix + key, num);
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			if (pool != null && jedis != null)
			{
//				pool.returnResourceObject(jedis);
				jedis.close();
			}
		}
	}
	
	/**
	 * 将key中的数值减一
	 * @param key
	 * @return
	 */
	public long Decr (Integer index, String key) 
	{
		JedisPool pool = null;
		Jedis jedis = null;
		try
		{
			pool = getEnableCacheWriter();
			jedis = pool.getResource();
			if (index == null)
			{
				index = DEFAULT_INDEX;
			}
			jedis.select(index);
			return jedis.decr(keyPerfix + key);
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			if (pool != null && jedis != null)
			{
//				pool.returnResourceObject(jedis);
				jedis.close();
			}
		}
	}
	
	/**
	 * 将key中的数值减num
	 * @param key
	 * @param num
	 * @return
	 */
	public long Decrby (Integer index, String key, int num) 
	{
		JedisPool pool = null;
		Jedis jedis = null;
		try
		{
			pool = getEnableCacheWriter();
			jedis = pool.getResource();
			if (index == null)
			{
				index = DEFAULT_INDEX;
			}
			jedis.select(index);
			return jedis.decrBy(keyPerfix + key, num);
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			if (pool != null && jedis != null)
			{
//				pool.returnResourceObject(jedis);
				jedis.close();
			}
		}
	}
	
	/**
	 * 向list的头部添加obj对象
	 * @param key
	 * @param obj
	 */
	public long lpush(Integer index, String key, Object obj) 
	{
		JedisPool pool = null;
		Jedis jedis = null;
		try
		{
			String json = this.ObjectToJSON(obj);
			pool = getEnableCacheWriter();
			jedis = pool.getResource();
			if (index == null)
			{
				index = DEFAULT_INDEX;
			}
			jedis.select(index);
			return jedis.lpush(keyPerfix + key, json);
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			if (pool != null && jedis != null)
			{
//				pool.returnResourceObject(jedis);
				jedis.close();
			}
		}
	}
	
	/**
	 * 向list的头部添加obj对象
	 * @param key
	 * @param obj
	 */
	public long lpush(Integer index, String key, String obj) 
	{
		JedisPool pool = null;
		Jedis jedis = null;
		try {
			pool = getEnableCacheWriter();
			jedis = pool.getResource();
			if (index == null)
			{
				index = DEFAULT_INDEX;
			}
			jedis.select(index);
			return jedis.lpush(keyPerfix + key, obj);
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			if (pool != null && jedis != null)
			{
//				pool.returnResourceObject(jedis);
				jedis.close();
			}
		}
	}
	
	/**
	 * 向list的头部添加obj对象
	 * @param key
	 * @param objs
	 */
	public long lpush(Integer index, String key, String... objs) 
	{
		JedisPool pool = null;
		Jedis jedis = null;
		try {
			pool = getEnableCacheWriter();
			jedis = pool.getResource();
			if (index == null)
			{
				index = DEFAULT_INDEX;
			}
			jedis.select(index);
			return jedis.lpush(keyPerfix + key, objs);
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			if (pool != null && jedis != null)
			{
//				pool.returnResourceObject(jedis);
				jedis.close();
			}
		}
	}
	
	/**
	 * 向list的尾部添加obj对象
	 * @param key
	 * @param obj
	 */
	public long rpush(Integer index, String key, Object obj) 
	{
		JedisPool pool = null;
		Jedis jedis = null;
		try {
			String json=this.ObjectToJSON(obj);
			pool = getEnableCacheWriter();
			jedis = pool.getResource();
			if (index == null)
			{
				index = DEFAULT_INDEX;
			}
			jedis.select(index);
			return jedis.rpush(keyPerfix + key, json);
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			if (pool != null && jedis != null)
			{
//				pool.returnResourceObject(jedis);
				jedis.close();
			}
		}
	}
	
	/**
	 * 向list的尾部添加obj对象
	 * @param key
	 * @param objs
	 */
	public long rpush(Integer index, String key, String... objs) {
		JedisPool pool = null;
		Jedis jedis = null;
		try {
			pool = getEnableCacheWriter();
			jedis = pool.getResource();
			if (index == null)
			{
				index = DEFAULT_INDEX;
			}
			jedis.select(index);
			return jedis.rpush(keyPerfix + key, objs);
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			if (pool != null && jedis != null)
			{
//				pool.returnResourceObject(jedis);
				jedis.close();
			}
		}
	}
	
	/**
	 * 返回列表 key 中，下标为 index 的元素
	 * @param key
	 * @param index
	 * @param clz
	 * @return
	 */
	@SuppressWarnings({ "rawtypes" })
	public Object lindex(Integer dbIndex, String key, int index, Class clz) {
		JedisPool pool = null;
		Jedis jedis = null;
		try {
			pool = getEnableCacheReader();
			jedis = pool.getResource();
			if (dbIndex == null)
			{
				dbIndex = DEFAULT_INDEX;
			}
			jedis.select(dbIndex);
			String res = jedis.lindex(keyPerfix + key, index);
			jedis.close();
			if (res != null && res.equals("nil"))
			{
				log.error("# Error : not get correct Value of redis - "+res);
				return null;
			}
			return this.JSONToObject(res, clz);
		} catch (Exception e) {
			if (pool != null && jedis != null)
			{
//				pool.returnResourceObject(jedis);
				jedis.close();
			}
			throw new RuntimeException(e);
		}
	}
	
	/**
	 * 根据参数 count 的值，移除列表中与参数 value 相等的元素
	 * count > 0 : 从表头开始向表尾搜索，移除与 value 相等的元素，数量为 count 
	 * count < 0 : 从表尾开始向表头搜索，移除与 value 相等的元素，数量为 count 的绝对值
	 * count = 0 : 移除表中所有与 value 相等的值。
	 * @param key
	 * @param obj
	 */
	public Long lrem(Integer index, String key, int count, Object obj) {
		JedisPool pool = null;
		Jedis jedis = null;
		try {
			String json = this.ObjectToJSON(obj);
			pool = getEnableCacheWriter();
			jedis = pool.getResource();
			if (index == null)
			{
				index = DEFAULT_INDEX;
			}
			jedis.select(index);
			return jedis.lrem(keyPerfix + key, count, json);
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			if (pool != null && jedis != null)
			{
//				pool.returnResourceObject(jedis);
				jedis.close();
			}
		}
	}
	
	/**
	 * 返回列表 key 的长度
	 * @param key
	 * @return
	 */
	public Long llen(Integer index, String key) 
	{
		JedisPool pool = null;
		Jedis jedis = null;
		try {
			pool= getEnableCacheReader();
			jedis= pool.getResource();
			if (index == null)
			{
				index = DEFAULT_INDEX;
			}
			jedis.select(index);
			return jedis.llen(keyPerfix + key);
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			if (pool != null && jedis != null)
			{
//				pool.returnResourceObject(jedis);
				jedis.close();
			}
		}
	}
	
	/**
	 * 对一个列表进行修剪(trim)，就是说，让列表只保留指定区间内的元素，不在指定区间之内的元素都将被删除。
	 * @param key
	 * @param start
	 * @param end
	 */
	public void ltrim(Integer index, String key, int start, int end) {
		JedisPool pool = null;
		Jedis jedis = null;
		try {
			pool = getEnableCacheWriter();
			jedis = pool.getResource();
			if (index == null)
			{
				index = DEFAULT_INDEX;
			}
			jedis.select(index);
			jedis.ltrim(keyPerfix + key, start, end);
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			if (pool != null && jedis != null)
			{
//				pool.returnResourceObject(jedis);
				jedis.close();
			}
		}
	}
	
	/**
	 * 返回列表 key 中指定区间内的元素，区间以偏移量 start 和 stop 指定
	 * @param key
	 * @param start
	 * @param end
	 * @param cls
	 * @return
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public List lrang(Integer index, String key, int start, int end, Class cls) 
	{
		JedisPool pool = null;
		Jedis jedis = null;
		try {
			pool = getEnableCacheReader();
			jedis = pool.getResource();
			if (index == null)
			{
				index = DEFAULT_INDEX;
			}
			jedis.select(index);
			List<String> res = jedis.lrange(keyPerfix + key, start, end);
			jedis.close();
			List list = new ArrayList();
			if (res != null && res.size() > 0)
			{
				res.parallelStream().forEach(obj -> list.add(JSONToObject(obj, cls)));
			}
			return list;
		} catch (Exception e) {
			if (pool != null && jedis != null)
			{
//				pool.returnResourceObject(jedis);
				jedis.close();
			}
			throw new RuntimeException(e);
		}
	}
	
	/**
	 * 返回列表 key 中指定区间内的元素，区间以偏移量 start 和 stop 指定
	 * @param key
	 * @param start
	 * @param end
	 * @return
	 */
	@SuppressWarnings({ "rawtypes" })
	public List lrang(Integer index, String key, int start, int end) 
	{
		JedisPool pool = null;
		Jedis jedis = null;
		try {
			pool = getEnableCacheReader();
			jedis = pool.getResource();
			if (index == null)
			{
				index = DEFAULT_INDEX;
			}
			jedis.select(index);
			return jedis.lrange(keyPerfix + key, start, end);
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			if (pool != null && jedis != null)
			{
//				pool.returnResourceObject(jedis);
				jedis.close();
			}
		}
	}
	
	/**
	 * set add member
	 * @param index
	 * @param key
	 * @param obj
	 */
	public void sadd(Integer index, String key, Object obj) 
	{
		JedisPool pool = null;
		Jedis jedis = null;
		try {
			String json = this.ObjectToJSON(obj);
			pool = getEnableCacheWriter();
			jedis = pool.getResource();
			if (index == null)
			{
				index = DEFAULT_INDEX;
			}
			jedis.select(index);
			jedis.sadd(keyPerfix + key, json);
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			if (pool != null && jedis != null)
			{
//				pool.returnResourceObject(jedis);
				jedis.close();
			}
		}
	}
	
	/**
	 * set remove member
	 * @param index
	 * @param key
	 * @param obj
	 */
	public void srem(Integer index, String key, Object obj) 
	{
		JedisPool pool = null;
		Jedis jedis = null;
		try {
			String json = this.ObjectToJSON(obj);
			pool = getEnableCacheWriter();
			jedis = pool.getResource();
			if (index == null)
			{
				index = DEFAULT_INDEX;
			}
			jedis.select(index);
			jedis.srem(keyPerfix + key, json);
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			if (pool != null && jedis != null)
			{
//				pool.returnResourceObject(jedis);
				jedis.close();
			}
		}
	}
	
	/**
	 * set get all members
	 * @param index
	 * @param key
	 */
	public Set<String> smembers(Integer index, String key) 
	{
		JedisPool pool = null;
		Jedis jedis = null;
		try {
			pool = getEnableCacheWriter();
			jedis = pool.getResource();
			if (index == null)
			{
				index = DEFAULT_INDEX;
			}
			jedis.select(index);
			return jedis.smembers(keyPerfix + key);
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			if (pool != null && jedis != null)
			{
//				pool.returnResourceObject(jedis);
				jedis.close();
			}
		}
	}
	
	/**
	 * set get all members
	 * @param index
	 * @param key
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public Set smembers(Integer index, String key, Class cls) 
	{
		JedisPool pool = null;
		Jedis jedis = null;
		try {
			pool = getEnableCacheWriter();
			jedis = pool.getResource();
			if (index == null)
			{
				index = DEFAULT_INDEX;
			}
			jedis.select(index);
			Set<String> res = jedis.smembers(keyPerfix + key);
			jedis.close();
			Set sets = new HashSet();
			if (res != null && res.size() > 0)
			{
				res.parallelStream().forEach(obj -> sets.add(JSONToObject(obj, cls)));
			}
			return sets;
		} catch (Exception e) {
			if (pool != null && jedis != null)
			{
//				pool.returnResourceObject(jedis);
				jedis.close();
			}
			throw new RuntimeException(e);
		}
	}
	
	/**
	 * set is exists member
	 * @param index
	 * @param key
	 * @param obj
	 * @return
	 */
	public boolean sismember(Integer index, String key, Object obj) 
	{
		JedisPool pool = null;
		Jedis jedis = null;
		try {
			String json = this.ObjectToJSON(obj);
			pool = getEnableCacheWriter();
			jedis = pool.getResource();
			if (index == null)
			{
				index = DEFAULT_INDEX;
			}
			jedis.select(index);
			return jedis.sismember(keyPerfix + key, json);
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			if (pool != null && jedis != null)
			{
//				pool.returnResourceObject(jedis);
				jedis.close();
			}
		}
	}
	
	public Long time() 
	{
		JedisPool pool = null;
		Jedis jedis = null;
		try {
			pool = getEnableCacheWriter();
			jedis = pool.getResource();
			List<String> list = jedis.time();
			jedis.close();
			Long time = list.size()>0 && StringUtils.isNotBlank(list.get(0))?Long.valueOf(list.get(0)):null;
			return time;
		} catch (Exception e) {
			if (pool != null && jedis != null)
			{
//				pool.returnResourceObject(jedis);
				jedis.close();
			}
			throw new RuntimeException(e);
		}
	}
	
	public String ping() 
	{
		JedisPool pool = null;
		Jedis jedis = null;
		try {
			pool= getEnableCacheWriter();
			jedis= pool.getResource();
			return jedis.ping();
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			if (pool != null && jedis != null)
			{
//				pool.returnResourceObject(jedis);
				jedis.close();
			}
		}
	}
	
}
